package com.xlabs.client;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.users.User;

import javax.jdo.annotations.*;
import javax.jdo.PersistenceManager;
import java.util.List;
import java.util.ArrayList;
import java.util.Date;

/**
 * TimedComment Data object.
 */
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class CommentDO {

    /**
     * Primary key.
     */
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Key key;

    /**
     * The text comment.
     */
    @Persistent
    private String comment;

    /**
     * time of comment.
     */
    @Persistent
    private double time;

    /**
     * Is this a reply or a question ?
     */
    @Persistent
    private Boolean isReply;

    /**
     * The video that has this comment.
     */
    @Persistent
    private Key video;

    /**
     * Replies to this comment.
     */
    @Persistent
    private List<Key> replies;

    /**
     * The question for this reply.
     */
    @Persistent
    private Key replyTo;

    /**
     * The parent comment. Is not null for all comments other than the root questions.
     */
    @Persistent
    private Key relatedTo;

    /**
     * When created.
     */
    @Persistent
    private Date createdOn;

    /**
     * Created by user.
     */
    @Persistent
    private User createdBy;

    /**
     * Initializes an instance of TimedComment.
     *
     * @param comment The comment.
     * @param time time.
     */
    public CommentDO(String comment, double time, Date createdOn) {
        this.comment = comment;
        this.time = time;
        this.createdOn = createdOn;
    }

    /**
     * Gets the key.
     *
     * @return id.
     */
    public Key getKey() {
        return key;
    }

    /**
     * Sets the key.
     * @param key key.
     */
    public void setKey(Key key)
    {
        this.key = key;
    }

    /**
     * Gets comment.
     *
     * @return comment.
     */
    public String getComment() {
        return comment;
    }

    /**
     * Sets Comment.
     *
     * @param comment The text comment.
     */
    public void setComment(String comment) {
        this.comment = comment;
    }

    /**
     * Gets video.
     *
     * @return video.
     */
    public Key getVideo() {
        return video;
    }

    /**
     * Sets video
     *
     * @param video video that has this comment.
     */
    public void setVideo(Key video) {
        this.video = video;
    }

    /**
     * Gets time.
     *
     * @return time.
     */
    public double getTime() {
        return time;
    }

    /**
     * Sets time.
     *
     * @param time time of comment.
     */
    public void setTime(double time) {
        this.time = time;
    }

    /**
     * Gets replies.
     * @return List of replies.
     */
    public List<Key> getReplies() {
        return replies;
    }

    /**
     * Sets replies.
     * @param replies List of replies.
     */
    public void setReplies(List<Key> replies) {
        this.replies = replies;
    }

    /**
     * Adds a reply.
     * @param replyKey reply key.
     */
    public void addReply(Key replyKey)
    {
        if (this.replies == null)
        {
            this.replies = new ArrayList<Key>();
        }
        this.replies.add(replyKey);
    }

    /**
     * Gets the parent comment.
     * @return parent comment.
     */
    public Key getRelatedTo() {
        return relatedTo;
    }

    /**
     * Sets relatedTo.
     * @param relatedTo parent comment.
     */
    public void setRelatedTo(Key relatedTo) {
        this.relatedTo = relatedTo;
    }

    /**
     * Returns the encoded Key of this jdo as a string.
     * @return encoded key.
     */
    public String getEncodedKey() {
        return KeyFactory.keyToString(this.key);
    }

    /**
     * Gets replyTo
     * @return Question to which this a reply.
     */
    public Key getReplyTo() {
        return replyTo;
    }

    /**
     * Sets replyTo.
     * @param replyTo Question to which this is a reply.
     */
    public void setReplyTo(Key replyTo) {
        this.replyTo = replyTo;
    }

    /**
     * isReply.
     * @return true iff if this is a reply, false if it' a question.
     */
    public Boolean isReply() {
        return isReply;
    }

    /**
     * setReply
     * @param reply Whether this is a reply ?
     */
    public void setReply(Boolean reply) {
        isReply = reply;
    }

    /**
     * Returns all comments sorted by time
     *
     * @return result.
     */
    public static CommentDTO[] getAllQuestions() {
        PersistenceManager pm = PMF.get().getPersistenceManager();

        try {
            String allCommentsQuery = "SELECT FROM " + CommentDO.class.getName() + " WHERE isReply == false ORDER BY time ASC ";
            List<CommentDO> allCommentDOs = (List<CommentDO>) pm.newQuery(allCommentsQuery).execute();

            return CommentDO.toCommentDTOArray(allCommentDOs);
        }
        finally {
            pm.close();
        }
    }

    /**
     * Gets createdOn.
     * @return time of creation.
     */
    public Date getCreatedOn() {
        return createdOn;
    }

    /**
     * Sets time of creation.
     * @param createdOn time of creation.
     */
    public void setCreatedOn(Date createdOn) {
        this.createdOn = createdOn;
    }

    /**
     * Gets createdBy.
     * @return creator.
     */
    public User getCreatedBy() {
        return createdBy;
    }

    /**
     * Sets createdBy.
     * @param createdBy creator.
     */
    public void setCreatedBy(User createdBy) {
        this.createdBy = createdBy;
    }

    /**
     * Converts an array of CommentDO objects to an array of TimedCommentDTO.
     * @param allCommentDOs
     * @return
     */
    public static CommentDTO[] toCommentDTOArray(List<CommentDO> allCommentDOs) {
        CommentDTO[] comments = new CommentDTO[allCommentDOs.size()];

        int index = 0;
        for (CommentDO aCommentDO : allCommentDOs) {
            comments[index++] = aCommentDO.toCommentDTO();
        }

        return comments;
    }

    /**
     * Converts this objecto to CommentDTO.
     * @return com.xlabs.client.CommentDTO
     */
    public CommentDTO toCommentDTO() {
        CommentDTO dto = new CommentDTO();

        dto.setComment(this.getComment());
        dto.setTime(this.getTime());
        dto.setEncodedKey(this.getEncodedKey());
        dto.setCreatedBy(this.getCreatedBy().getNickname());
        dto.setCreatedOn(this.getCreatedOn());

        return dto;
    }
}